<?php
declare (strict_types = 1);

namespace app\common\libs\module;

use app\admin\model\MenuModel;
use app\admin\model\ModuleModel;
use app\admin\service\BaseService;
use app\admin\service\ModuleService;
use app\common\libs\helper\FileHelper;
use app\common\libs\helper\SqlHelper;
use think\facade\Db;

/**
 * 模块安装
 *
 * @Author tanruizheng
 * @DateTime 2021-07-30
 */
class ModuleInstall extends BaseService
{
    private $module;

    public function __construct($module)
    {
        $this->module = $module;
    }

    /**
     * 执行文件安装
     *
     * @Author tanruizheng
     * @DateTime 2021-07-30
     * @return void
     */
    public function run(){
        Db::startTrans();
        $module = $this->module;//安装模块
        try {
            //设置脚本最大执行时间
            set_time_limit(0);
            //检查是否已经安装
            $moduleInfo = ModuleModel::where('module',$module)->findOrEmpty()->toArray();
            if(!empty($moduleInfo)){
                return self::createFail('模块已经安装');
            }
            //加载配置文件
            $moduleInfo = ModuleService::getModuleInfo($module);
            if(!$moduleInfo['status']){
                return self::createFail('配置文件加载失败');
            }
            $config = $moduleInfo['data'];
            $data = [
                'module'        => $module,
                'modulename'    => $config['modulename'],
                'disabled'      => 0,
                'version'       => $config['version'],
                'installtime'   => time(),
                'updatetime'    => time(),
                'listorder'     => 0,
            ];
            $res = ModuleModel::create($data);
            if(!$res){
                return self::createFail('安装初始化失败');
            }
    
            //执行数据库脚本安装
            $res = $this->runSql($module);
            if(!$res['status']){
                $this->installRollback($module);
                return $res;
            }
            //执行菜单项安装
            $res = $this->installMenu($module);
            if(!$res['status']){
                $this->installRollback($module);
                return $res;
            }
            //执行静态文件安装
            $this->copyResource($module);
            //安装完成
            Db::commit();
            return self::createSuccess('安装完成');
        } catch (\Exception $e) {
            $this->installRollback($module);
            return self::createFail($e->getMessage());
        }
       
    }

    /**
     * 执行数据库脚本安装
     *
     * @Author tanruizheng
     * @DateTime 2021-07-30
     * @param [type] $module
     * @param string $dir
     * @return void
     */
    public function runSql($module, $dir = 'install'){
        if(empty($module)){
            return self::createFail('模块不能为空');
        }
        //sql文件路径
        $sqlPath = base_path() . strtolower("{$module}/{$dir}/") . "{$module}.sql";
        if(!file_exists($sqlPath)){
            return self::createFail('sql文件不存在');
        }
        $sql = file_get_contents($sqlPath);
        $sqlHelper = new SqlHelper();
        $sql = $sqlHelper->splitSQL($sql);
        if(!empty($sql) && is_array($sql)){
            foreach ($sql as $item) {
                Db::execute($item);
            }
        }
        return self::createSuccess('完成sql安装');
    }

    /**
     * 安装模块回滚
     *
     * @Author tanruizheng
     * @DateTime 2021-07-30
     * @param [type] $module
     * @return void
     */
    public function installRollback($module){
        ModuleModel::where('module',$module)->delete();
        Db::rollback();
        return self::createSuccess('模块回滚完成');
    }

    /**
     * 执行菜单项安装
     *
     * @Author tanruizheng
     * @DateTime 2021-07-30
     * @return void
     */
    public function installMenu($module){
        //menu菜单路径
        $menuPath = base_path() . strtolower("{$module}/install/") . "Menu.php";
        if(!file_exists($menuPath)){
            return self::createFail('Menu文件不存在');
        }
        $menu = include $menuPath;
        if(empty($menu)){
            return self::createFail('没有菜单数据');
        }
        return $this->createInstallMenu($menu);
    }

    public function createInstallMenu($data, $parentid = 0){
        foreach ($data as $item) {
            $route = explode('/',$item['route']);
            $newData = [
                'app' => $route[0],
                'controller' => $route[1],
                'action' => $route[2],
                'name' => $item['name'],
                'parentid' => $parentid,
                'type' => isset($item['type']) ? $item['type'] : 1,
                'status' => isset($item['status']) ? $item['status'] : 0,
                'remark' => $item['remark'] ?: '',
                'listorder' => isset($item['listorder']) ? $item['listorder'] : 0,
                'parameter' => isset($item['parameter']) ? $item['parameter'] : '',
                'icon' => isset($item['icon']) ? $item['icon'] : '',
            ];
            $menuId = MenuModel::insertGetId($newData);
            if(isset($item['child']) && $item['child']){
                $this->createInstallMenu($item['child'],$menuId);
            }
        }
        return self::createSuccess('安装菜单完成');
    }

     /**
     * 执行静态文件安装
     *
     * @Author tanruizheng
     * @DateTime 2021-07-30
     * @param [type] $module
     * @param string $dir
     * @return void
     */
    public function copyResource($module){
        if(empty($module)){
            return self::createFail('模块不能为空');
        }
        //静态资源文件路径
        $resourceDir = base_path() . strtolower("{$module}/install/extra/");
        if(!is_dir($resourceDir)){
            return self::createFail('静态资源文件不存在');
        }

        $toPath = public_path().'/static/extra/'.strtolower($module).'/';
        $fileHelper = new FileHelper();
        $res = $fileHelper->copyDir($resourceDir, $toPath);
        if(!$res){
            return self::createFail('静态资源文件安装失败');
        }
        return self::createSuccess('完成静态资源文件安装');
    }

}
